using System;
using Kopernikus.Collections.ThreadSafe;
using Kopernikus.Parsing.GenericActions;

namespace Kopernikus.Parsing
{
    public class GenericParser<TParser, S>
    {
        private static readonly ThreadSafeDictionary<Type, GenericEvaluator<TParser, S>> m_evaluators =
            new ThreadSafeDictionary<Type, GenericEvaluator<TParser, S>>();

        private readonly GenericEvaluator<TParser, S> m_evaluator;

        private GenericParser(GenericEvaluator<TParser, S> evaluator)
        {
            m_evaluator = evaluator;
        }


        public static GenericParser<TParser, S> Create(TParser instance)
        {
            GenericEvaluator<TParser, S> evaluator =
                m_evaluators.GetValue(instance.GetType(), delegate { return new GenericEvaluator<TParser, S>(); });
            return new GenericParser<TParser, S>(evaluator.Clone(instance));
        }

        public S Parse(string s)
        {
            return
                m_evaluator.Parser.Parse(m_evaluator,
                                         GenericLexer<TParser, S>.Create(m_evaluator.TargetInstance).GenericScan(s));
        }
    }
}